package top.overstep.zboot.system.commons.shiro;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.overstep.zboot.commons.enums.CodeMessageEnum;
import top.overstep.zboot.commons.exception.ZBootException;
import top.overstep.zboot.system.config.RegularConfig;
import top.overstep.zboot.system.dao.UserMapper;
import top.overstep.zboot.system.domain.Menu;
import top.overstep.zboot.system.domain.Role;
import top.overstep.zboot.system.domain.User;
import top.overstep.zboot.system.service.MenuService;
import top.overstep.zboot.system.service.RoleService;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author codeZzz
 *
 */
@Component
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserMapper userMapper;
    @Resource
    private RoleService roleService;
    @Resource
    private MenuService menuService;


    @Autowired
    private RegularConfig regularConfig;

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //取出用户主体信息
        User principal = (User) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if (principal == null) {
            return null;
        }
        //查询用户的角色
        List<Role> roles = roleService.findRolesByUserId(principal.getUserId());
        //用户角色表示
        Set<String> roleSet = roles.stream().map((role) -> role.getRoleSign()).collect(Collectors.toSet());
        info.setRoles(roleSet);
        List<Long> roleIds = roles.stream().map((role) -> role.getRoleId()).collect(Collectors.toList());
        //权限
        List<Menu> menus = menuService.selectMenusByRoleIds(roleIds);
        Set<String> perms = menus.stream().map((menu) -> menu.getPerms()).collect(Collectors.toSet());
        info.setStringPermissions(perms);
        return info;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String loginName = token.getUsername();
        //查询user
        User user = this.getUserByLoginName(loginName);
        //封装查询结果
        return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes("salt"), this.getName());
    }

    private User getUserByLoginName(String loginName) {
        if (loginName == null) {
            throw new ZBootException(CodeMessageEnum.PARAM_ERROR.getMessage(), CodeMessageEnum.PARAM_ERROR.getCode());
        }

        User user = null;
        //匹配正则
        if (loginName.matches(regularConfig.getRegularMap().get(RegularConfig.MOBILE_KEY))) {
            //手机号
            user = new User();
            user.setMobile(loginName);
            user = userMapper.selectOne(user);
        } else if (loginName.matches(regularConfig.getRegularMap().get(RegularConfig.EMAIL_KEY))) {
            //邮箱
            user = new User();
            user.setEmail(loginName);
            user = userMapper.selectOne(user);
        } else {
            //用户名
            user = new User();
            user.setUsername(loginName);
            user = userMapper.selectOne(user);
        }

        if (user == null) {
            throw new UnknownAccountException();
        }
        //用户被禁止登录
        if (user.getStatus().equals(0)) {
            throw new LockedAccountException();
        }
        return user;
    }

}
